﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Build.Framework;
using System.IO;
using System.Xml;
using System.CodeDom;
using Microsoft.CSharp;
using System.CodeDom.Compiler;

namespace XAMLResourceEnhancer
{
    public class Enhancer : ITask
    {
        public IBuildEngine BuildEngine{get;set;}
        public ITaskHost HostObject { get; set; }

        [Required]
        public string ResourceDirectory { get; set; }


        public bool Execute()
        {
            BuildEngine.LogMessageEvent(new BuildMessageEventArgs("Using Enhancer to create usable resources from generated XAML", string.Empty, "Enhancer", MessageImportance.High));
            try
            {
                DirectoryInfo dir = new DirectoryInfo(this.ResourceDirectory);
                foreach (FileInfo fi in dir.EnumerateFiles("*.xaml"))
                {
                    string vbName = fi.Name.Replace(".xaml", "");

                    XmlDocument doc = new XmlDocument();
                    using (FileStream inStream = fi.OpenRead())
                    {
                        doc.Load(inStream);
                        inStream.Close();
                    }
                    XmlAttribute c = doc.CreateAttribute("x", "Class", "http://schemas.microsoft.com/winfx/2006/xaml");
                    c.Value = "WpfAlarmTimer.Resources." + vbName;
                    doc.DocumentElement.Attributes.Append(c);
                    using (FileStream xmlOut = fi.Open(FileMode.Create))
                    {
                        XmlWriterSettings settings = new XmlWriterSettings();
                        settings.Encoding = Encoding.UTF8;
                        settings.OmitXmlDeclaration = false;
                        settings.IndentChars = "    ";
                        settings.NewLineChars = "\r\n";
                        settings.Indent = true;
                        XmlWriter writer = XmlWriter.Create(xmlOut, settings);
                        doc.WriteTo(writer);
                        writer.Flush();
                        xmlOut.Close();
                        BuildEngine.LogMessageEvent(new BuildMessageEventArgs(string.Format("Enhancer added x:Class to {0}", fi.Name), string.Empty, "Enhancer", MessageImportance.Low));
                    }

                    var unit = new CodeCompileUnit();
                    unit.ReferencedAssemblies.Add("System");
                    unit.ReferencedAssemblies.Add("System.Windows.Controls");
                    var ns = new CodeNamespace("WpfAlarmTimer.Resources");
                    var t = new CodeTypeDeclaration(vbName);
                    t.IsPartial = true;
                    t.IsClass = true;
                    t.BaseTypes.Add(new CodeTypeReference("System.Windows.Controls.Viewbox"));
                    var ctor = new CodeConstructor();
                    ctor.Attributes = MemberAttributes.Public;
                    var ctorEx = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "InitializeComponent", new CodeExpression[] { });
                    ctor.Statements.Add(ctorEx);
                    t.Members.Add(ctor);
                    ns.Types.Add(t);
                    unit.Namespaces.Add(ns);
                    var provider = new CSharpCodeProvider();
                    using (Stream outStream = new FileStream(fi.FullName + ".cs", FileMode.Create))
                    {
                        var tw = new StreamWriter(outStream);
                        var sw = new IndentedTextWriter(tw);
                        provider.GenerateCodeFromCompileUnit(unit, sw, null);
                        sw.Flush();
                    }
                    BuildEngine.LogMessageEvent(new BuildMessageEventArgs(string.Format("Enhancer generated {0}.cs", fi.Name), string.Empty, "Enhancer", MessageImportance.Low));
                }
                return true;
            }
            catch (Exception) {
                return false;
            }
        }
    }
}
